package com.xyy.saas.payment.adpater.jd.common;

import com.alibaba.fastjson.JSONObject;
import com.xyy.saas.payment.common.Constants;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.util.ApolloUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.*;

@Slf4j
public class JDConstants {

    /****************************基本信息 start ************************************/
    /** 京东金融成功码  **/
    public static final String JD_CREDIT_SUCCESS_CODE = "0000000";

    /** 成功码：绑卡成功码标识  **/
    public static final String SUCCESS_CODE = "0000";
    public static final String SUCCESS_CODE_0 = "00000";  // jd_card部分数据回调成功状态码不一致 待确认

    /** 成功码：聚合支付成功码标识  **/
    public static final String SUCCESS_CODE_AGGRATE = "0000";
    /** 成功码：cardbin成功码标识  **/
    public static final String SUCCESS_CODE_CARBIN = "00000";
    /** 签约渠道  **/
    public static final String CHANNEL_CONTRACT = Constants.CHANNEL_JD_CARD_NAME;
    /** 协议签约时的支付协议  **/
    public static final String PAYMENT_AGREEMENT_URL = "https://qiye.jd.com/contractCenter2_noHead.html#/template-preview?cid=00006&sid=GRZF&tid=7145407";
    /** 协议签约结果回调业务侧 **/
    public static final String CONTRACT_CALLBACK = "ecJdBindCardResult";
    /** 京东融资采购准入结果回调业务侧 **/
    public static final String JD_CREDIT_CALLBACK = "ec_jd_credit";
    /**************************** 默认字段 ************************************/
    /** 业务类型  **/
    public static final String BIZ_TYPE = "100001";
    /** 聚合支付-币种 **/
    public static final String AGGRATE_CURRENCY = "CNY";
    /** 聚合支付-版本 **/
    public static final String AGGRATE_VERSION = "V2";
    /** 聚合支付-用户ip **/
    public static final String AGGRATE_USER_IP = getIpAddress();
    /** 聚合支付-报文格式 **/
    public static final String AGGRATE_MESSAGE_FORMAT = "JDPAY031";
    /** 聚合支付-订单类型 **/
    public static final String AGGRATE_ORDER_TYPE = "p";

    /****************************请求地址配置****************************************/
    /** 京东api地址 **/
    public static final String URL_DOMAIN = "https://wapi.jd.com";
    /** 一键签约银行列表 **/
    public static final String URL_queryOneKeySignBanks = URL_DOMAIN + "/api/queryOneKeySignBanks";
    /** 一键签约申请接口 **/
    public static final String URL_oneKeySignApply = URL_DOMAIN + "/api/oneKeySignApply";
    /** 签约结果查询接口 **/
    public static final String URL_queryOneKeySignResult = URL_DOMAIN + "/api/queryOneKeySignResult";
    /** 协议签约接口 **/
    public static final String URL_contractSign = URL_DOMAIN + "/api/contractSign";
    /** 协议确认接口 **/
    public static final String URL_contractSignConfirm = URL_DOMAIN + "/api/contractSignConfirm";
    /** 协议解约接口 **/
    public static final String URL_cancelContract = URL_DOMAIN + "/api/cancelContract";
    /** 协议支付接口 **/
    public static final String URL_saleByContractNo = URL_DOMAIN + "/api/saleByContractNo";
    /** 退款接口 **/
    public static final String URL_tradeRefund = URL_DOMAIN + "/api/tradeRefund";
    /** 订单查询 **/
    public static final String URL_tradeQuery = URL_DOMAIN + "/api/query";
    /** 京东卡渠道信息查询 **/
    public static final String URL_CARDBIN = "https://psp.jdpay.com/service/standard.htm";

    /** 京东聚合支付 (**/
    /** 三方聚合统一收单 url **/
    public static final String AGGREGATE_CREATE_ORDER_URL = URL_DOMAIN + "/api/createAggregateOrder";
    /** 交易查询 url **/
    public static final String TRADE_QUERY_URL = URL_DOMAIN + "/api/queryOrder";
    /** 退款申请 url **/
    public static final String REFUND_URL = URL_DOMAIN + "/api/refund";
    /** 退款查询 url **/
    public static final String REFUND_QUERY_URL = URL_DOMAIN + "/api/refundQuery";
    /** 关单 url **/
    public static final String CLOSE_URL = URL_DOMAIN + "/api/close";

    /** 需要做预警监控的接口 **/
    public static final List<String> ALARM_URL = Arrays.asList(
            //URL_queryOneKeySignBanks, URL_oneKeySignApply, URL_contractSign, URL_contractSignConfirm,
            //URL_cancelContract, URL_saleByContractNo, URL_tradeRefund, URL_CARDBIN,
            //AGGREGATE_CREATE_ORDER_URL, REFUND_URL
    );

    /****************************回调配置 start ************************************/
    /** 签约结果回调method **/
    public static final String CALLBACK_CONTRACT_METHOD_PREFIX = "contract";
    /** 京东采购融资回调method **/
    public static final String JD_CREDIT_PAY_CALLBACK_METHOD = "jdcdtNotice";
    /** 京东采购融资准入method **/
    public static final String JD_CREDIT_CONTRACT_CALLBACK_METHOD = "jdContract";
    /** 数据类型 key  **/
    public static final String PARAM_FORMAT_TYPE = "formatType";
    /** 签名类型 key  **/
    public static final String PARAM_SIGN_TYPE = "signType";
    /** 签名数据 key  **/
    public static final String PARAM_SIGN = "signData";
    /** 加密类型 key  **/
    public static final String PARAM_ENC_TYPE = "encType";
    /** 加密数据 key  **/
    public static final String PARAM_ENC_DATA = "encData";

    /****************************通用信息 start ************************************/
    /** 字符集 **/
    public static final String CHARSET_UTF8 = "UTF-8";
    /** 数据格式 **/
    public static final String DATA_FORMAT_TYPE_JSON = "JSON";
    /** 签名类型 **/
    public static final String SING_TYPE ="SHA-256";
    /** 加密类型-新api接口证书加密  **/
    public static final String ENCRYPT_TYPE_AP7 ="AP7";

    /**************************** 京东配置信息获取 ************************************/
    /** 获取商户号的signKey */
    public static String merchantSignKey(String logPrefix, String merchantNo) throws PaymentException {
        return getMerchantSetting(logPrefix, merchantNo, "signKey");
    }
    /** 获取商户号的password */
    public static String merchantPassword(String logPrefix, String merchantNo) throws PaymentException {
        return getMerchantSetting(logPrefix, merchantNo, "password");
    }
    /** 获取商户号的subMerchant */
    public static String merchantSubMerchant(String logPrefix, String merchantNo) throws PaymentException {
        return getMerchantSetting(logPrefix, merchantNo, "subMerchant");
    }
    /** 获取商户号的aesKey */
    public static String merchantAesKey(String logPrefix, String merchantNo) throws PaymentException {
        return getMerchantSetting(logPrefix, merchantNo, "aesKey");
    }

    /** 获取绑卡支付商户号 */
    public static String cardMerchant(String logPrefix, String businessType) throws PaymentException {
        return jdPaySetting(logPrefix, businessType, "cardMerchantNo");
    }

    /** 获取聚合支付商户号
     * channel:jdaggregate_wx,jdaggregate_alipay
     *
     * */
    public static String aggregateMerchant(String logPrefix, String channel,String businessType) throws PaymentException {
        return jdPaySetting(logPrefix, businessType, channel+"MerchantNo");
    }

    /** 获取聚合支付小程序APPID */
    public static String aggregateWxAppID(String logPrefix, String businessType) throws PaymentException {
        return jdPaySetting(logPrefix, businessType, "WxAppid");
    }
    /** 获取聚合支付小程序原始APPID */
    public static String aggregateWxMiniUserName(String logPrefix, String businessType) throws PaymentException {
        return jdPaySetting(logPrefix, businessType, "WXMiniUserName");
    }
    /** 获取聚合支付小程序秘钥 */
    public static String aggregateWxSecret(String logPrefix, String businessType) throws PaymentException {
        return jdPaySetting(logPrefix, businessType, "WxAppSecret");
    }

    private static String jdPaySetting(String logPrefix, String businessType, String key) throws PaymentException {
        String setting = ApolloUtil.getProperty(Constants.JD_PAY_SETTING + businessType);
        log.info("{} 获取聚合支付配置:{} {} {}", logPrefix, businessType, key, setting);
        if (StringUtils.isBlank(setting)) {
            log.error("{} 业务{}未配置支付信息", logPrefix, businessType);
            throw new PaymentException(ResultCodeEnum.DEFAULT_ERROR);
        }
        JSONObject settingJSON = JSONObject.parseObject(setting);
        if (!settingJSON.containsKey(key)) {
            log.error("{} 业务{}未配置支付信息{}", logPrefix, businessType, key);
            throw new PaymentException(ResultCodeEnum.DEFAULT_ERROR);
        }
        return settingJSON.getString(key);
    }

    private static String getMerchantSetting(String logPrefix, String merchantNo, String key) throws PaymentException {
        String setting = ApolloUtil.getProperty(Constants.JD_PAY_MERCHANT_SETTING + merchantNo);
        log.info("{} 获取京东商户号配置信息:{} {} {}", logPrefix, merchantNo, key, setting);
        if (StringUtils.isBlank(setting)) {
            String property = ApolloUtil.getProperty(Constants.JD_PAY_MERCHANT_SETTING + merchantNo + "." + key);
            log.info("{} 查询原配置信息 {} {}", logPrefix, merchantNo, property);
            if (StringUtils.isNotBlank(property)) {
                return property;
            }
            log.error("{} {}未配置商户号信息", logPrefix, merchantNo);
            throw new PaymentException(ResultCodeEnum.DEFAULT_ERROR);
        }
        JSONObject settingJSON = JSONObject.parseObject(setting);
        if (!settingJSON.containsKey(key)) {
            log.error("{} {}未配置商户号信息{}", logPrefix, merchantNo, key);
            throw new PaymentException(ResultCodeEnum.DEFAULT_ERROR);
        }
        return settingJSON.getString(key);
    }

    private static Map<String, String> COMPARE = new HashMap<>();
    static {
        COMPARE.put("idName", "持卡人姓名错误");
        COMPARE.put("idNo", "持卡人证件号错误");
        COMPARE.put("phone", "持卡人手机号错误");
        COMPARE.put("bankCode", "银行编码错误");
        COMPARE.put("cardNo", "银行卡号错误");
        COMPARE.put("verifyCode", "验证码错误，请重新输入");
        COMPARE.put("contractNo", "签约协议号错误");
    }

    /**
     * 错误码转换
     */
    public static String transMsg(String logPrefix, String code, String message) {
        if (StringUtils.isBlank(code) || StringUtils.isBlank(message)) {
            return message;
        }
        log.info("{} error_msg {} {}", logPrefix, code, message);
        if (COMPARE.containsKey(message)) {
            return COMPARE.get(message);
        }
        if ("CARDPAM300002".equals(code.trim()) || message.trim().startsWith("参数错误：")) {
            String[] cols = message.split("：");
            if (cols.length < 2) {
                return message;
            }
            String col = cols[1];
            if (COMPARE.containsKey(col)) {
                return COMPARE.get(col);
            } else {
                return "参数错误";
            }
        }
        return message;
    }

    /**
     * 获取服务器IP地址
     */
    private static String getIpAddress() {
        try {
            Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip;
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                if (netInterface.isLoopback() || netInterface.isVirtual() || !netInterface.isUp()) {
                    continue;
                } else {
                    Enumeration addresses = netInterface.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        ip = (InetAddress) addresses.nextElement();
                        if (ip != null && ip instanceof Inet4Address) {
                            return ip.getHostAddress();
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("IP地址获取失败{}", e);
        }
        return "127.0.0.1";
    }

}
